#include "stdafx.h"
#include "problem_solver_core.h"
#include "problem.h"
#include "solver.h"
#include "MLP.h"
#include "layer.h"
#include "neuron.h"
#include "output_neuron.h"

namespace nnse
{
	extern io_module io_m;

	// Constructor and Destructor

	template <class T, class U> output_neuron<T, U>::output_neuron(layer<T, U>^ p, unsigned int n_n)
	: neuron<T, U>(p, n_n)
	{
		io_m.startup_stream << "Constructing output neuron " << get_number() << std::endl;
		layer<T, U>% previous_layer=get_parent_MLP()->get_layer(get_parent_layer()->get_number()-1);
		put_number_of_dendrites(previous_layer.get_number_of_neurons());
		put_dendrites();
	}

	template <class T, class U> output_neuron<T, U>::~output_neuron()
	{
		io_m.startup_stream << "Destructing output neuron " << get_number() << std::endl;
	}

	// Worker Functions

	template <class T, class U> void output_neuron<T, U>::forward(layer<T, U>% dummy_next_layer, bool dummy_update_flag)
	{
		put_NET();
		put_OUT();
	}

	template <class T, class U> U output_neuron<T, U>::reverse(layer<T, U>% dummy_next_layer)
	{
		put_ERR(dummy_next_layer);
		put_DELTA();
		filter_back_DELTA();
		return 0.5*get_DELTA()*get_DELTA();
	}

	template <class T, class U> U output_neuron<T, U>::calc_OUT()
	{
		U OUT = neuron::calc_OUT();
		get_parent_solver()->put_output_value(get_number(), OUT);
		return OUT;
	}

	template <class T, class U> U output_neuron<T, U>::calc_ERR(layer<T, U>% dummy_next_layer)
	{
		get_parent_problem()->put_target_flag();
		return get_parent_problem()->get_value(get_number())-get_OUT();
	}

	// Serialisation Functions

	template <class T, class U> void output_neuron<T, U>::display(std::wofstream& out)
	{
		out << "Output Neuron:" << std::endl;
		neuron<T, U>::display(out);
	}

	// Explicit Instantiation

	template ref class output_neuron<bool, double>;
	template ref class output_neuron<unsigned char, double>;
}
